/*******************************************************************************
 * Copyright (c) 2011 Irineu Martins de Lima Moura (imlm2).
 * This file is part of JBeat.
 * 
 *     JBeat is free software: you can redistribute it and/or modify
 *     it under the terms of the GNU Lesser General Public License as published by
 *     the Free Software Foundation, either version 3 of the License, or
 *     (at your option) any later version.
 * 
 *     JBeat is distributed in the hope that it will be useful,
 *     but WITHOUT ANY WARRANTY; without even the implied warranty of
 *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *     GNU Lesser General Public License for more details.
 * 
 *     You should have received a copy of the GNU Lesser General Public License
 *     along with JBeat.  If not, see <http://www.gnu.org/licenses/>.
 * 
 * Contributors:
 *     Irineu Martins de Lima Moura (imlm2) - initial API and implementation
 ******************************************************************************/
package br.ufpe.cin.imlm2.jbeat.soot.common;

import java.util.Calendar;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import soot.SceneTransformer;
import soot.tagkit.Host;
import br.ufpe.cin.imlm2.util.options.IOptions;
import br.ufpe.cin.imlm2.util.options.NoSuchOptionException;
import br.ufpe.cin.imlm2.util.options.Parameterizable;
import br.ufpe.cin.imlm2.util.options.ParsingException;

/**
 * An abstract tagger for the Soot Scene. The general idea is that a Tagger
 * works over a set of Hosts (the <i>targetSet</i>) doing any kind of analysis
 * and usually tagging the results in the Hosts. <i>targetSet</i>.
 * 
 * @author Irineu
 */
public abstract class Tagger extends SceneTransformer implements Parameterizable {

	protected Set<Host> targetSet;
	protected IOptions options;

	public Tagger( IOptions options ) {
		super();
		this.options = options;
		this.setTargetSet( new HashSet<Host>() );
	}

	@SuppressWarnings("unchecked")
	@Override
	protected void internalTransform( String phaseName, Map options ) {
		try {
			this.options.parse( options );
		} catch ( NoSuchOptionException e ) {
			throw new RuntimeException( "Invalid option '" + e.getInvalidOtion() );
		} catch ( ParsingException e ) {
			throw new RuntimeException( "Unable to parse phase options.", e );
		}

		this.resolveTargetSet();
		this.executePreTaggingTransformations();
		System.err.println( this.getClass().getSimpleName() + " beggining at "
				+ Calendar.getInstance().getTime() );
		Long startTime = System.currentTimeMillis();
		this.tag();
		System.err.println( this.getClass().getSimpleName() + " finished in "
				+ (System.currentTimeMillis() - startTime) + "ms at "
				+ Calendar.getInstance().getTime() );
		this.executePostTaggingTransformations();
	}

	protected abstract void resolveTargetSet();

	protected abstract void tag();

	/**
	 * Execute some post-processing or cleanup after doing the analysis.
	 */
	protected abstract void executePostTaggingTransformations();

	/**
	 * Execute some pre-processing or setup required by this Tagger.
	 */
	protected abstract void executePreTaggingTransformations();

	@Override
	public IOptions getOptions() {
		return options;
	}

	protected void setTargetSet( Set<Host> targetSet ) {
		this.targetSet = targetSet;
	}

	protected Set<Host> getTargetSet() {
		return targetSet;
	}

}
